home *** CD-ROM | disk | FTP | other *** search
/ NetNews Offline 2 / NetNews Offline Volume 2.iso / news / comp / lang / c++-part1 / 581 < prev    next >
Encoding:
Text File  |  1996-08-05  |  4.1 KB  |  101 lines

  1. Path: newsfeed.internetmci.com!panix!usenet
  2. From: Jeffrey O. Katz <off@panix.com>
  3. Newsgroups: comp.lang.c++
  4. Subject: Re: How best to handle constructor failure?
  5. Date: 5 Jan 1996 08:15:53 GMT
  6. Organization: Scientific Consultant Services, Inc.
  7. Message-ID: <4cimnp$hne@news1.panix.com>
  8. References: <4c36gl$5e5@nnrp1.news.primenet.com>
  9. NNTP-Posting-Host: off.dialup.access.net
  10. X-Newsreader: SPRY News 3.03 (SPRY, Inc.)
  11.  
  12. >   Robert DiFalco <difalco@primenet.com> writes:
  13. >  >
  14. >  >     My problem is how to best test for constructor success (sufficient memory,
  15. >  > successful allocations) or failure (insuficient memory condition).  In straight C, I would
  16. >  > simply try to allocate my arrays, and, if unable to, I would free any that were allocated
  17. >  > and then return a NULL pointer to my structure.  In C++, however, constructors do
  18. >  > not have a return value - so I cannot test for a bad return value - and, sometimes
  19. >  > they are called by the compiler to generate temporaries, for example when operators
  20. >  > are overloaded - another place where there may be a not-enough-memory situation.
  21. >  >
  22. >
  23. >  Is there something wrong with C++ exceptions? If you are worried about
  24. >  memory leaks, just use auto pointers on your dynamic arrays. I don't know
  25. >  what your code is like, but say you have something like one of the
  26. >  following:
  27. >
  28. >   SomeClass::SomeClass( ... )
  29. >   {
  30. >      try
  31. >      {
  32. >         auto_ptr<SomeArray> a1 = new SomeArray();
  33. >         auto_ptr<SomeArray> a2 = new SomeItem[ SOME_AMOUNT ];
  34. >         .
  35. >         . Maybe you even have code here where you raise the exception
  36. >         .
  37. >      }
  38. >      catch ( exception x )
  39. >      {
  40. >         .
  41. >         . <handle failure here>
  42. >         .
  43. >      }
  44. >   }
  45. >
  46. >  By using the auto_ptr's, when the stack is cleaned-up, the objects
  47. >  <a1> and <a2> point to will be deleted in the auto_ptr destructor. If you
  48. >  want, you can get the try...catch logic out of your constructor and put
  49. >  it around the calls to this constructor. In any event, I'm not advocating
  50. >  that you copy this code into your program, you really need to develop an
  51. >  exception strategy, but this should point you in the right direction
  52. >  (unless I misunderstood your question).
  53. >
  54. >  Robert
  55. >
  56. >>>>
  57.  
  58.     Yes, using auto pointers will avoid memory leaks from un-destructed objects.
  59. The problem, however, is how to alter the sequence of code existing OUTSIDE of
  60. the constructor, based on the success or failure of the constructor.
  61.  
  62.     In addition, we cannot use exceptions for a variety of reasons (e.g., some
  63. functions must be exported from a DLL using a straight C or PASCAL calling
  64. convention, and errors need to be handled by a calling application written in
  65. another language), and, even if we could, it appears that we would still need
  66. to use a longjmp() inside the try {...} in order to get out of the constructor so as
  67. to be able to bypass the code that follows the constructor in the function.  Using
  68. longjmp(), an initializer method that is called seperately from the constructor,
  69. or various "test" methods (a method that returns a success/failure value) makes
  70. code kludgy and inelegant.  I was wondering what the "correct" approach (if
  71. there is such a thing) for handling the problem was.
  72.  
  73. To make the problem a little clearer, what we need to do is something like this:
  74.  
  75.   int MyFunction (int n, float y, ...)  {
  76.     MyClass mc(n);
  77.     int return_code;
  78.     if (constructor failed entirely) {
  79.         rc = STACK_OVERFLOW;
  80.     } else if (allocations internal to the constructor failed) {
  81.         rc = INSUFFICIENT_HEAP;
  82.     } else {
  83.         ... lots of code ...
  84.         rc = SUCCESS;
  85.     }
  86.     return rc;
  87.     // the implicitly called destructor will perform any needed cleanup
  88.   }
  89.  
  90.  I noticed that there was another thread on constructors that was recently posted,
  91. where a suggestion was made to use a seperate initialization function (what I called
  92. a "test" method").  I have done this upon occasion, but I need to overload operators,
  93. and hence there will be compiler-generated, implicit constructor calls which would
  94. not include execution of the seperate initializer method!  The issue of dealing with
  95. constructors that can fail appears to be a complex one.  Perhaps a good thread
  96. will start on the subject!.
  97.  
  98.     Jeff
  99.  
  100.  
  101.